package org.agiletestplus.client.ui;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.agiletestplus.client.objects.Configuration;
import org.agiletestplus.client.objects.ConfigurationType;
import org.agiletestplus.client.objects.Project;
import org.damour.base.client.objects.PermissibleObject;
import org.damour.base.client.service.BaseServiceCache;
import org.damour.base.client.ui.IGenericCallback;
import org.damour.base.client.ui.buttons.Button;
import org.damour.base.client.ui.dialogs.IDialogCallback;
import org.damour.base.client.ui.dialogs.MessageDialogBox;
import org.damour.base.client.ui.dialogs.PromptDialogBox;

import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.CaptionPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.VerticalPanel;

public class ManageConfigurationsPanel extends HorizontalPanel {
  
  IGenericCallback<Project> callback = null;
  ListBox configTypeList = new ListBox();
  HorizontalPanel centerPanel = new HorizontalPanel();
  
  List<ConfigurationType> configList = null;
  
  public ManageConfigurationsPanel(IGenericCallback<Project> callback) {
    this.callback = callback;
    buildUI();
    fetchConfigurationTypes();
  }
   
  public void fetchConfigurationTypes() {
    final AsyncCallback<List<PermissibleObject>> loadCallback = new AsyncCallback<List<PermissibleObject>>() {
      public void onFailure(Throwable caught) {
        Window.alert("Failure.");
      }
      @SuppressWarnings({ "unchecked", "rawtypes" })
      public void onSuccess(final List<PermissibleObject> configurationTypes) {
        configTypeList.clear();
        if (configurationTypes != null && configurationTypes.size() > 0) {
          configList = (List<ConfigurationType>)(List)configurationTypes;
          for (final ConfigurationType obj : configList) {
            configTypeList.addItem(obj.getName());
          }
        }
      };
    };
    BaseServiceCache.getService().getPermissibleObjects(null, "org.agiletestplus.client.objects.ConfigurationType", loadCallback);
  }
  
  private void buildUI() {
        
    configTypeList.setVisibleItemCount(15);
    configTypeList.addItem("Loading...");
    configTypeList.setWidth("200px");
    configTypeList.addChangeHandler(new ChangeHandler() {
      @Override
      public void onChange(ChangeEvent event) {
        if (configTypeList.getSelectedIndex() >= 0) {
          final ConfigurationType configType = configList.get(configTypeList.getSelectedIndex());
          final EditConfigurationTypePanel panel = new EditConfigurationTypePanel(configType);
          CaptionPanel captionPanel = new CaptionPanel("Edit Configuration Type");
          VerticalPanel vp = new VerticalPanel();
          vp.add(panel);
          HorizontalPanel buttonPanel = new HorizontalPanel();
          Button saveButton = new Button("Save");
          Button cancelButton = new Button("Cancel");
          buttonPanel.add(saveButton);
          buttonPanel.add(cancelButton);
          saveButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
              configType.setName(panel.getName());
              configType.setDescription(panel.getDescription());
              final AsyncCallback<Void> saveCallback = new AsyncCallback<Void>() {
                public void onFailure(Throwable caught) {
                  MessageDialogBox dialog = new MessageDialogBox("Error", "Could not edit configuration type.", true, true, true);
                  dialog.center();
                }

                public void onSuccess(Void v) {
                  MessageDialogBox dialog = new MessageDialogBox("Success", "Configuration Type Saved.", true, true, true);
                  dialog.center();
                  centerPanel.clear();
                  fetchConfigurationTypes();
                };
              };
              
              Set<PermissibleObject> allObjs = new HashSet<PermissibleObject>();
              allObjs.add(configType);
              for (Configuration config : panel.configurationList) {
                config.setConfigurationType(configType);
              }
              allObjs.addAll(panel.configurationList);
              
              BaseServiceCache.getService().deleteAndSavePermissibleObjects(panel.toRemove, allObjs, saveCallback);
                
            }
          });
          cancelButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                centerPanel.clear();
            }
          });
          vp.add(buttonPanel);
          captionPanel.add(vp);
          centerPanel.clear();
          centerPanel.add(captionPanel);
        }
      }
    });
    
    setHeight("100%");
    setWidth("100%");

    HorizontalPanel buttonPanel = new HorizontalPanel();
    Button newButton = new Button("New...");
    Button deleteButton = new Button("Delete");
    
    Button refreshButton = new Button("Refresh");
    refreshButton.addClickHandler(new ClickHandler() {
      public void onClick(ClickEvent event) {
        configTypeList.clear();
        configTypeList.addItem("Loading...");
        // setWidget(0, 1, new Label());
        fetchConfigurationTypes();
      }
    });
    
    newButton.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        // update right panel to be "add"
        final ConfigurationType type = new ConfigurationType();
        final EditConfigurationTypePanel panel = new EditConfigurationTypePanel(type);
        panel.applyConfigurations(new ArrayList<Configuration>());
        CaptionPanel captionPanel = new CaptionPanel("New Configuration Type");
        VerticalPanel vp = new VerticalPanel();
        vp.add(panel);
        HorizontalPanel buttonPanel = new HorizontalPanel();
        Button addButton = new Button("Add");
        Button cancelButton = new Button("Cancel");
        buttonPanel.add(addButton);
        buttonPanel.add(cancelButton);
        
        addButton.addClickHandler(new ClickHandler() {
          @Override
          public void onClick(ClickEvent event) {
            // add
            type.setName(panel.getName());
            type.setDescription(panel.getDescription());
            final AsyncCallback<List<PermissibleObject>> saveCallback = new AsyncCallback<List<PermissibleObject>>() {
              public void onFailure(Throwable caught) {
                MessageDialogBox dialog = new MessageDialogBox("Error", "Could not edit configuration type.", true,
                    true, true);
                dialog.center();
              }

              public void onSuccess(List<PermissibleObject> savedProject) {
                if (savedProject == null) {
                  MessageDialogBox dialog = new MessageDialogBox("Error", "Could not edit configuration type.", true,
                      true, true);
                  dialog.center();
                } else {
                  // store configurations with config type

                  MessageDialogBox dialog = new MessageDialogBox("Success", "Configuration Type Created.", true, true,
                      true);
                  dialog.center();
                  centerPanel.clear();
                  fetchConfigurationTypes();
                }
              };
            };
            List<PermissibleObject> allObjs = new ArrayList<PermissibleObject>();
            allObjs.add(type);
            for (Configuration config : panel.configurationList) {
              config.setConfigurationType(type);
            }
            allObjs.addAll(panel.configurationList);
            BaseServiceCache.getService().savePermissibleObjects(allObjs, saveCallback);

          }
        });
        
        cancelButton.addClickHandler(new ClickHandler() {
          @Override
          public void onClick(ClickEvent event) {
              centerPanel.clear();
          }
        });
        
        vp.add(buttonPanel);
        captionPanel.add(vp);
        centerPanel.clear();
        centerPanel.add(captionPanel);
      }
      
    });

    deleteButton.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        if (configTypeList.getSelectedIndex() >= 0) {
          final ConfigurationType configType = configList.get(configTypeList.getSelectedIndex());
          PromptDialogBox dialog = new PromptDialogBox("Delete Configuration Type", "Yes", null, "No", true, true);
          dialog.setCallback(new IDialogCallback() {
            public void okPressed() {
              centerPanel.clear();
              AsyncCallback<Void> deleteCallback = new AsyncCallback<Void>() {
                @Override
                public void onFailure(Throwable caught) {
                  MessageDialogBox dialog = new MessageDialogBox("Error", "An error occurred while deleting the configuration type: " + caught.getMessage(), true, true, true);
                  dialog.center();
                }
  
                @Override
                public void onSuccess(Void result) {
                  MessageDialogBox dialog = new MessageDialogBox("Success", "Configuration type deleted.", true, true, true);
                  dialog.center();
                  fetchConfigurationTypes();
                }
              };
              BaseServiceCache.getService().deletePermissibleObject(configType, deleteCallback);
            }
  
            public void cancelPressed() {
            }
          });
          dialog.setContent(new HTML("Are you sure you want to delete " + configType.getName()+ "?"));
          dialog.center();
        }
      }
    });

    buttonPanel.add(newButton);
    buttonPanel.add(deleteButton);
    buttonPanel.add(refreshButton);
    
    CaptionPanel captionPanel = new CaptionPanel("Configuration Types (OS, Browser, etc)");
    VerticalPanel leftPanel = new VerticalPanel();
    captionPanel.setContentWidget(leftPanel);

    leftPanel.add(configTypeList);
    leftPanel.add(buttonPanel);
    add(captionPanel);

    add(centerPanel);    
  }
}
